﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Common.Systems.Memory
{
    /** 内存管理、优化方法 **/
    public class Memory
    {
        private static readonly Version myVersion = new Version(1, 0);

        /**
           * \brief 将当前进程的内存占用尺寸设置到最小
           *
           * \retval 是否运行成功，0为成功,-1为失败
           */
        public static int SetProcessMemoryToMin()
        {
            return SetProcessMemoryToMin(Process.GetCurrentProcess().Handle);
        }

        /**
           * \brief 将内存占用尺寸设置到最小
           *
           * \param SetProcess 需要设置内存使用范围的程序进程句柄，一般为当前进程， 如：System.Diagnostics.Process.GetCurrentProcess().Handle</param>
           * \retval 是否运行成功，0为成功,-1为失败
           */
        public static int SetProcessMemoryToMin(IntPtr SetProcess)
        {
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                return SetProcessWorkingSetSize(SetProcess, -1, -1);
            }
            return -1;
        }

        /**
           * \brief 调整GC待处理内存大小，强行激活CLR内存回收处理机制
           * \param[in] size 待处理内存
           * \retval void 空
           */
        public static void MemoryPressureDemo(int size)
        {
            //创建一组对象，并指定它们的逻辑大小
            new BigNativeResource(size);
            //为了演示，强制回收前面的这一组对象
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

        private sealed class BigNativeResource
        {
            private int m_size;
            public BigNativeResource(int size)
            {
                m_size = size;
                if (m_size > 0)
                {
                    GC.AddMemoryPressure(size);//让垃圾回收器认为对象在物理上比较大
                }
            }

            ~BigNativeResource()
            {
                if (m_size > 0)
                {
                    GC.RemoveMemoryPressure(m_size);//让垃圾回收器认为释放了更多的内存
                }
            }
        }

        [DllImport("kernel32.dll")]
        private static extern int SetProcessWorkingSetSize(IntPtr hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
    }
}
